<?php
class DB_Mysqli {
    protected $table;
    private $charset = 'utf8';

    static $db;
    private $lastSql = '';

    private $where = '';
    private $fields = '*';
    private $limit = '';

    private $errorInfo;
    private $debug;


    private $model = [];

    /**
     * 显示sql报错
     */
     public function error($bool) {
         $this->debug = $bool;
         if(self::$db->error) {
             $this->errorInfo = "sql: {$this->lastSql}<br/>\n" . " error:{self::$db->error}";
            if($bool) {
                 echo $this->errorInfo;exit;
            } else {
                Log::write($this->errorInfo, 'sql错误', './logs/dberror/');
            }

         }
         return $this->errorInfo;
     }

    /**
     * 连接数据库
     * @param  [type] $config [description]
     * @return [type]         [description]
     */
    public function connet($config) {

        self::$db = new mysqli(
            $config['host'], //连接地址
            $config['user'],//帐号
            $config['pass'],//密码
            $config['database'], //使用的数据库
            $config['port'] //端口号
        );
        $this->error($config['debug']);
        if(self::$db->connect_error){
            Log::write(self::$db->conncet_error, '数据库连接失败', './logs/dberror/');
            trigger_error('database: no connect');die;
        }
        if (!self::$db->set_charset($this->charset)) {
            Log::write(sprintf("Error loading charset: %s\n", self::$db->error), '设置字符集出错: ' . $this->charset, './logs/dberror/');
            trigger_error('database: charset error');die;
        }
        return $this;
    }

    /**
     * 设置查询返回字段
     * @param  string $fields [description]
     * @return [type]         [description]
     */
    public function field($fields='*') {
        $this->fields = $fields;
        return $this;
    }
    /**
     * 设置操作的表
     * @param [type] $table [description]
     */
    public function setTable($table) {
        $this->table = $table;
        return $this;
    }
    /**
     * 设置字符集
     * @param [type] $charset [description]
     */
    public function setCharset($charset) {
        $this->charset = $charset;
        return $this;
    }
    public function limit($offset='',$size='') {
        if($offset) {
            $this->limit = "limit $offset";
        }
        if($offset && $size) {
            $this->limit = "limit $offset, $size";
        }
        return $this;
    }
    /**
     * 查询记录数
     * @return 返回结果集
     */
    public function gets() {
        if (!$this->table) {
            return false;
        }
        $this->lastSql = $sql = "select {$this->fields} from {$this->table} {$this->where} $this->limit";
        $data = [];
        $sql = addslashes($sql);
        if($result = self::$db->query($sql)) {
            while ($row = $result->fetch_assoc()) {
                $data[] = $row;
            }
        } else {
            $this->error($this->debug);
        }
        $this->clear();

        return $data;
    }
    /**
     * 获取单条记录数
     * @return [type] [description]
     */
    public function get($where='') {
        return $this->where($where)->limit(1)->gets()[0];
    }
    /**
     * 删除记录
     * @return [type] [受影响的行数]
     */
    public function delete() {
        if (!$this->table) {
            return false;
        }
        $this->lastSql = $sql = "delete from {$this->table} {$this->where}";
        $sql = addslashes($sql);
        if($this->where) {
            $result = self::$db->query($sql);
            $this->error($this->debug);
            if(!$result) {

                return 0;
            }
            $this->where='';
            return self::$db->affected_rows;
        }
        return 0;
    }

    private function array_callback(&$array, $callback) {
        foreach ($array as  &$value) {
            if(FALSE === $callback($value)){
                return;
            }
        }
    }
    /**
     * 新增多条记录
     * @param  [type] $data 多维键值对数组
     * @return [type]       [description]
     */
    public function inserts($data) {
        if (!$this->table) {
            return false;
        }
        $sql = "INSERT INTO {$this->table} ";
        if(!$data[0]) return false;
        $fields = '(' . implode(',',array_keys($data[0])) . ') ';
        $values = "VALUES";

        foreach ($data as $key => $value) {
            $temp_value = array_values($value);

            /**
             * 将字符串值加上单引号
             * @var string
             */
            $this->array_callback($temp_value,function(&$item){
                if(is_string($item)) {
                    $item = "'$item'";
                }
            });


            $values .= '(' . implode(',',$temp_value) . '),';
        }
        $this->lastSql = $sql .= $fields . trim($values,',');
        $sql = addslashes($sql);
        if($result = self::$db->query($sql)) {
            $this->clear();
            return self::$db->insert_id;
        } else {
            $this->error($this->debug);
        }
        return false;
    }

    /**
     * 新增单条记录
     * @param  [type] $data [一维键值对]
     * @return [type]       [description]
     */
    public function insert($data) {
        return $this->inserts([$data]);
    }
    /**
     * 更新记录
     */
     public function update($data) {
         if (!$this->table) {
             return false;
         }

         $sql = "UPDATE {$this->table}";
         $fields = ' SET ';
         foreach ($data as $key => $value) {
             if(is_string($value)) {
                 $fields .= "`$key` = '$value',";
             } else {
                 $fields .= "`$key` = $value,";
             }
         }
         $this->lastSql = $sql = $sql . trim($fields, ',') . $this->where;
         if(!$this->where) return false;
         $sql = addslashes($sql);
         if($result = self::$db->query($sql)) {
             $this->clear();
             return self::$db->affected_rows;
         } else {
             $this->error($this->debug);
         }
         return false;
     }

    /**
     * 拼接where条件
     * @param  [type] $condtion [description]
     * @return [type]           [description]
     */
    public function where($condtion='') {
        $where = '';
        if(is_array($condtion)) {
            foreach ($condtion as $key => $value) {
                if(!is_string($value)) {
                    $where .= " $key = $value AND";
                } else {
                    $where .= " $key = '$value' AND";
                }
            }
            $where = rtrim($where, 'AND');
        } else {
            $where = $condtion;
        }
        if($where) {
            $this->where = ' WHERE ' . $where;
        }
        return $this;
    }

    /**
     * 添加要关联的模型
     * @param [type] $model [description]
     */
    public function joinModels(Array $models) {
        $this->model = $models;
        return $this;
    }
    /**
     * 关联查询[一对一,一对多]
     * @param $leftKey 主表的关联字段
     * @param $toMany  为ture表示默认为一对多,false 一对一
     * @return [type] [description]
     */
    public function joinGets($leftKey,$toMany=true) {
        $models = $this->model;
        $leftData = $this->gets();
        $inJoins = array_column($leftData, $leftKey);
        $son = [];
        foreach ($models as $key => &$obj) {
            $thData = $obj->where("`$key` in (".implode(',',$inJoins).")")->gets();
            foreach ($thData as $v) {
                $son[$obj->table][$v[$key]][] = $v;
            }
        }
        foreach ($leftData as $index => &$value) {
            foreach ($son as $table => $v) {

                if($toMany) {
                    if (isset($v[$value[$leftKey]])) {
                        $value[$table] = $v[$value[$leftKey]];
                    } else {
                        unset($leftData[$index]);
                    }
                } else {
                    if (isset($v[$value[$leftKey]][0])) {
                        $value[$table] = $v[$value[$leftKey]][0];
                    } else {
                        unset($leftData[$index]);
                    }
                }
            }
        }
        return $leftData;
    }

    /**
     * 关联查询[一对一]
     * @return [type] [description]
     */
    public function joinGet($leftKey) {
        return $this->joinGets($leftKey,false);
    }


    //查询的sql语句
    public function sql() {
        $sql = "select {$this->fields} from {$this->table} {$this->where} ";
        $this->clear();
        return $sql;
    }
    public function lastSql() {
        return $this->lastSql;
    }

    public function clear() {
        $this->where='';
        $this->model=[];
        $this->fields='*';
        return $this;
    }


}
